package jgespres;

import java.io.File;
import java.io.FilenameFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.*;
import java.awt.Component;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.*;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import java.util.logging.*;
import java.util.Date;
import java.util.Locale;
import java.util.Properties;
import java.util.ResourceBundle;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;

/**
 * Gestionnaire de présentation
 *
 * @author guerfyld
 * @version 2.0
 */
public class jgespres extends JFrame {
    // Constantes
    public static final String VERSION = "2.0";
    public static final java.sql.Date NULLDATE = java.sql.Date.valueOf("0001-01-01");
    public static final String NULL = "";
    public static final int MAXSESSION = 9;

    private static final String PRJNAME = "jGesPres";
    private static final String PRJDIRECTORY = ".jgespres";
    private static final String PRJPROPERTIESFILE = "jgespres.properties";
    private static final String PRJLOGFILE = "jgespres.log";
    private static final String RPTDIRECTORY = "report";

    // Connexion JDBC
    private Connection connect;

    // Elements à gerer
    private SchoolClass schoolClass;
    private ThemesCatalog themesCatalog;
    private Tables tables;
    private Planning planning;

    private String curPath;
    private Properties properties;
    private Logger logger;
    private static ResourceBundle resources;

    /**
     * Constructeur
     */
    public jgespres() {
        // Initialisation application
        init();

        // Ouverture connexion JDBC
        logger.log(Level.INFO, "Ouverture connexion jdbc...");
        String jdbcDriver = properties.getProperty("jdbcDriver");
        String jdbcUrl = properties.getProperty("jdbcUrl");
        try {
            // Chargement du pilote JDBC
            logger.log(Level.CONFIG, "- JDBCDriver=" + jdbcDriver);
            Class.forName(jdbcDriver);

            // Etablissement de la connexion
            logger.log(Level.CONFIG, "- JDBCUrl=" + jdbcUrl);
            connect = DriverManager.getConnection(jdbcUrl, "","");

            // Vérification Base de données
            JBaseDlg.checkBase(connect);
        }
        catch(Exception e) {
            JBaseDlg dialog = new JBaseDlg();
            if (dialog.baseChanged()) {
                connect = dialog.getConnection();
                saveConnection(dialog.getDriver(), dialog.getUrl());
                dialog.dispose();
            }
            else {
                logger.log(Level.SEVERE, "Erreur de connection (Driver="+jdbcDriver+", Url="+jdbcUrl+") !");
                System.exit(1);
            }
        }

        // Création des objets à gerer
        schoolClass   = new SchoolClass(connect);
        themesCatalog = new ThemesCatalog(connect);
        tables        = new Tables(connect);
        planning      = new Planning(connect, schoolClass, themesCatalog, tables);

        // Construction de l'interface
        createGUI();
    }

    private void init() {
        try {
            // Determination répertoire fichier des propriétés
            // - Recherche en premier dans répertoire courant
            // - Puis dans répertoire $HOME\.jgespres
            curPath = (new File(".")).getCanonicalPath();
            File propFile = new File(curPath, PRJPROPERTIESFILE);
            if(!propFile.exists()) {
                String savPath = curPath;
                curPath = System.getProperty("user.home");
                if (curPath.equals("")) {
                    curPath = savPath;
                }
                else {
                    // Si aucun fichier trouvé, création d'un fichier dans $HOME\.jgespres
                    File f = new File(curPath, PRJDIRECTORY);
                    if (!f.exists()) 
                        f.mkdir();
                    curPath = f.getCanonicalPath();
                    propFile = new File(curPath, PRJPROPERTIESFILE);
                }
            }
            
            // Chargement fichier de propriétés
            propFile = new File(curPath, PRJPROPERTIESFILE);
            properties = new Properties();
            if (propFile.exists()) {
                // Lecture fichier
                FileInputStream fis = new FileInputStream(propFile);
                properties.load(fis);
                fis.close();
                // Mise à jour langue courante
                String language = properties.getProperty("language");
                if (language != null)
                    Locale.setDefault(new Locale(language));
            }

            // Chargement resources
            resources = ResourceBundle.getBundle("jgespres/Application");
        }
        catch (Exception e) {
            e.printStackTrace();
            System.exit(0);
        }

        // Redirection stderr et stdout vers fichier de log
        try {
            PrintStream out = new PrintStream(new FileOutputStream(new File(curPath, PRJLOGFILE)), true);
            System.setErr(out);
            System.setOut(out);
        }
        catch (Exception e) {}

        // Chargement logger et paramétrage
        logger = Logger.getLogger("jgespres");
        logger.setUseParentHandlers(false);
        ConsoleHandler ch = new ConsoleHandler();
        ch.setFormatter(new Formatter() {
            public String format(LogRecord record) {
                Date date = new Date(record.getMillis());
                return date +
                    " [" + record.getSourceClassName() + "/" + record.getSourceMethodName() + "] " +
                    record.getLevel() + ": " + record.getMessage() + "\r\n";
            }
        });
        ch.setLevel(Level.ALL);
        logger.addHandler(ch);
        int lvl = 1;
        try {
            lvl = Integer.parseInt(properties.getProperty("loglevel"));
        }
        catch (Exception e) {}
        switch (lvl) {
            case 0: logger.setLevel(Level.OFF); break;
            case 1: logger.setLevel(Level.SEVERE); break;
            case 2: logger.setLevel(Level.WARNING); break;
            case 3: logger.setLevel(Level.INFO); break;
            case 4: logger.setLevel(Level.CONFIG); break;
            case 5: logger.setLevel(Level.FINE); break;
            case 6: logger.setLevel(Level.FINER); break;
            case 7: logger.setLevel(Level.FINEST); break;
            default: logger.setLevel(Level.ALL);
        }
    }

    private void createGUI() {
        // Définition des onglets
        logger.log(Level.FINEST, "Définition des onglets");
        JTabbedPane tabbedPane = new JTabbedPane();
        tabbedPane.setOpaque(true);
        // -> Planning
        final JPlanningMkr plgPanel = new JPlanningMkr(planning);
        tabbedPane.addTab(jgespres.getResourceString("Planning.TabLib"), new ImageIcon(getClass().getResource("/jgespres/images/Planning.png")), plgPanel);
        // -> Elèves
        JPanel panel = new JThemesMgr(themesCatalog);
        tabbedPane.addTab(jgespres.getResourceString("Theme.TabLib"), new ImageIcon(getClass().getResource("/jgespres/images/Themes.png")), panel);
        // -> Thémes
        panel = new JStudentsMgr(schoolClass);
        tabbedPane.addTab(jgespres.getResourceString("Student.TabLib"), new ImageIcon(getClass().getResource("/jgespres/images/Students.png")), panel);

        // Affecte un change listener à la fenêtre principale
        logger.log(Level.FINEST, "Affectation ChangeListener à la fenêtre principale");
        tabbedPane.addChangeListener(new ChangeListener() {
            // Methode appellée à chaque changement d'onglets
            public void stateChanged(ChangeEvent evt) {
                // Récupère onglet courant
                JTabbedPane pane = (JTabbedPane) evt.getSource();
                int sel = pane.getSelectedIndex();
                if (sel == 0)
                    plgPanel.refresh();
            }
        });

        // Définition de la barre de menu
        logger.log(Level.FINEST, "Définition de la barre de menu");
        JMenuBar menuBar = new JMenuBar();
        // -> Menu Fichier
        JMenu menu = new JMenu(jgespres.getResourceString("Menu.File"));
        JMenuItem menuItem = new JMenuItem(jgespres.getResourceString("Menu.Open"));
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                // Ouverture nouvelle base de données
                openBase();
            }
        });
        menu.add(menuItem);
        menu.addSeparator();
        menuItem = new JMenuItem(jgespres.getResourceString("Planning.Table"));
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                // Affichage boite de dialogue de gestion Table des paramètres
                JTableDlg dialog = new JTableDlg(tables);
                dialog.dispose();
                plgPanel.refresh();
            }
        });
        menu.add(menuItem);
        menu.addSeparator();
        menuItem = new JMenuItem(jgespres.getResourceString("Menu.Exit"));
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                beforeClosing();
                System.exit(0);
            }
        });
        menu.add(menuItem);
        menuBar.add(menu);
        // -> Menu Outils
        menu = new JMenu(jgespres.getResourceString("Menu.Tools"));
        menuItem = new JMenuItem(jgespres.getResourceString("Menu.Archive"));
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                // Affichage boite de dialogue de gestion de l'archivage
                archiveBase();
            }
        });
        menu.add(menuItem);
        menuItem = new JMenuItem(jgespres.getResourceString("Menu.Clean"));
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                // Affichage boite de dialogue de gestion de l'archivage
                cleanBase();
            }
        });
        menu.add(menuItem);
        menuBar.add(menu);
        // -> Menu Rapport
        menu = new JMenu(jgespres.getResourceString("Menu.Report"));
        // Récupération liste des rapports disponibles
        File[] files = getReportList();
        if (files != null) {
            for(int i=0; i<files.length; i++) {
                menuItem = new Report(files[i], planning, properties);
                menu.add(menuItem);
            }
        }
        menuBar.add(menu);
        // -> Menu Aide
        menu = new JMenu("?");
        menuItem = new JMenuItem(jgespres.getResourceString("Menu.Help"));
        menu.add(menuItem);
        menu.addSeparator();
        menuItem = new JMenuItem(jgespres.getResourceString("Menu.About"));
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                showAbout();
            }
        });
        menu.add(menuItem);
        menuBar.add(menu);

        // Préparation fenêtre principale (JFrame)
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle(PRJNAME);
        setContentPane(tabbedPane);
        setJMenuBar(menuBar);
        //pack();
        try {
            int h = Integer.parseInt(properties.getProperty("windowHeight"));
            int w = Integer.parseInt(properties.getProperty("windowWidth"));
            setSize(w, h);
        }
        catch (Exception e) {
            setSize(300, 300);
        }
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                beforeClosing();
            }
        });
    }

    private void saveConnection(String driver, String url) {
        try {
            // Affectation valeur des propriétés
            properties.setProperty("jdbcDriver", driver);
            properties.setProperty("jdbcUrl", url);
            // Ecriture fichier
            saveProperties();
        }
        catch (Exception e) {}
    }

    private void saveProperties() {
        try {
            // Ecriture fichier
            FileOutputStream fos = new FileOutputStream(new File(curPath, PRJPROPERTIESFILE));
            properties.store(fos, PRJNAME + " properties");
            fos.close();
        }
        catch (Exception e) {}
    }

    private void openBase() {
        // Sélection localisation de la base de données
        JBaseDlg dialog = new JBaseDlg();
        if (dialog.baseChanged()) {
            connect = dialog.getConnection();
            saveConnection(dialog.getDriver(), dialog.getUrl());
            schoolClass.setConnection(connect);
            themesCatalog.setConnection(connect);
            planning.setConnection(connect);
        }
        dialog.dispose();
    }

    private File[] getReportList() {
        File dir = new File(curPath, RPTDIRECTORY);
        return dir.listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.endsWith(".rpt");
            }
        });
    }

    private void showAbout() {
        JDialog dialog = new JDialog(JFrame.getFrames()[0], jgespres.getResourceString("Menu.About"), true);
        dialog.getContentPane().setLayout(new BoxLayout(dialog.getContentPane(), BoxLayout.Y_AXIS));
        dialog.setSize(249,150);
        dialog.setResizable(false);
        JLabel label = new JLabel(jgespres.PRJNAME);
        label.setAlignmentX(Component.CENTER_ALIGNMENT);
        label.setFont(label.getFont().deriveFont(18.0f));
        dialog.getContentPane().add(label);
        label = new JLabel(jgespres.getResourceString("Title"));
        label.setAlignmentX(Component.CENTER_ALIGNMENT);
        dialog.getContentPane().add(label);
        label = new JLabel(jgespres.getResourceString("Version")+" : "+jgespres.VERSION);
        label.setAlignmentX(Component.CENTER_ALIGNMENT);
        dialog.getContentPane().add(label);
        centerDialog(dialog);
        dialog.setVisible(true);
        dialog.dispose();
    }

    /**
     * Point d'entrée du programme
     *
     * @param args the command line arguments
     */
    public final static void main(String args[]) {
        final Frame Frm = new Frame();
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                new WaitWindow(Frm).setVisible(true);
            }
        });

        final jgespres j = new jgespres();
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                Frm.dispose();
                j.setVisible(true);
            }
        });
        }

    /**
     * Récupération resource de l'application
     *
     * @param key       Nom de Resource
     * @return          Resource
     */
    public static String getResourceString(String key)  {
        return resources.getString(key);
    }

    /**
     * Centre boite de dialogue
     */
    public static void centerDialog(Component cpt) {
        Frame frm = JFrame.getFrames()[0];

        int posx = (int)frm.getLocation().getX() + (frm.getWidth() - cpt.getWidth())/2;
        int posy = (int)frm.getLocation().getY() + (frm.getHeight() - cpt.getHeight())/2;
        if (posx < 0) posx = 0;
        if (posy < 0) posy = 0;
        cpt.setLocation(posx, posy);
    }
    
    private void beforeClosing() {
        // Affectation valeur des propriétés
        properties.setProperty("windowHeight", Integer.toString(this.getSize().height));
        properties.setProperty("windowWidth", Integer.toString(this.getSize().width));
        // Ecriture fichier
        saveProperties();
    }
    
    private void archiveBase() {
        final JDialog dialog = new JDialog(JFrame.getFrames()[0], jgespres.getResourceString("Menu.Archive"), true);
        dialog.setResizable(false);
        dialog.getContentPane().setLayout( new BoxLayout(dialog.getContentPane(), BoxLayout.Y_AXIS) );

        // Définition 1ére ligne
        JPanel line = new JPanel( new java.awt.FlowLayout(java.awt.FlowLayout.LEFT) );
        // -> Start date
        JLabel label = new JLabel(jgespres.getResourceString("Tools.ArchiveDate")+" :");
        label.setPreferredSize( new java.awt.Dimension(75, 25) );
        line.add(label);
        java.text.DateFormat df = java.text.DateFormat.getDateInstance(java.text.DateFormat.MEDIUM);
        String[] dateList = new String[planning.getRowCount()];
        for(int i =0; i<dateList.length; i++) {
            dateList[i] = df.format(themesCatalog.getDate(i));
        }
        final JComboBox cmbDateList = new JComboBox(dateList);
        cmbDateList.setPreferredSize( new java.awt.Dimension(100, 25) );
        line.add(cmbDateList);
        dialog.getContentPane().add(line);
        
        // Définition 2éme ligne
        line = new JPanel( new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT) );
        // -> Boutons d'action
        JButton button = new JButton(jgespres.getResourceString("Dialog.Ok"));
        button.setPreferredSize( new java.awt.Dimension(90, 25) );
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                DBTools.archiveDB(connect, themesCatalog.getDate(cmbDateList.getSelectedIndex()), logger);
                
                schoolClass.setConnection(connect);
                themesCatalog.setConnection(connect);
                planning.setConnection(connect);

                dialog.dispose();
            }
        });
        line.add(button);
        button.setPreferredSize( new java.awt.Dimension(90, 25) );
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                dialog.dispose();
            }
        });
        line.add(button);
        dialog.getContentPane().add(line);
        dialog.pack();
        centerDialog(dialog);
        
        // Affichage boite dialogue
        dialog.setVisible(true);
        
        // Destruction boite dialogue aprés utilisation
        dialog.dispose();
    }

    private void cleanBase() {
         class PrimeThread extends Thread {
            JDialog dia;
            PrimeThread(JDialog dia) {
                 this.dia = dia;
            }
 
            public void run() {
                for(int i=0; i<9999; i++) {
                    int c = i * i;
                    try {
                        this.wait(1000);
                    } catch (Exception e) {e.printStackTrace();}
                }
                dia.dispose();
            }
        }
        
        JPanel line = new JPanel( new java.awt.FlowLayout(java.awt.FlowLayout.LEFT) );
        JDialog dia = new JDialog(JFrame.getFrames()[0], "WAIT !", true);
        JLabel lab = new JLabel(new ImageIcon(getClass().getResource("/jgespres/images/CLOCK.GIF")));
        line.add(lab);
        lab = new JLabel("Please wait ....");
        line.add(lab);
        dia.getContentPane().add(line);
        dia.setUndecorated(true);
        dia.pack();
        centerDialog(dia);
        
        PrimeThread pth = new PrimeThread(dia);
        pth.start();
        
        dia.setVisible(true);

        if (JOptionPane.showConfirmDialog(null, "Choose one", jgespres.getResourceString("Menu.Clean"), JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
            DBTools.cleanDB(connect);
        }
    }
}
